package day18.Junit_reflect_annotation_proxy.annotationdemo;

import org.junit.Assert;
import org.junit.Test;


import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

@Mycharacter(name="小红",address = "北京")
public class demo1
{
    @Mycharacter(name="小紫",address = {"北京","上是海"})//注解就是告诉程序该如果具体处理这一片的代码块
    int a;
    @Test
@Mycharacter(name="小明",address = {"北京","上海"})//这是个注解的实例化对象。注解是个特殊的接口（一般的接口不能实例化但是特殊的可以），接口又是个特殊的类，所以这就是注解类的是实例化对象，封装了这些变量
    @Mycharacter2(name="小李",age=19,address = {"上海"})
      //拿到类的注解对象（实例化的）
      public void func1()
      {
           //现在第二个点就是该如何拿到修饰类或者变量或者方法的注解
          Class c1=demo1.class;
          //判断是否有注解
          if(c1.isAnnotationPresent(Mycharacter.class))//形参是class类型的。目的：看看是否有某个类型的注解。我要提供这个注解而且他要求是class类型，那就拿到MyCharacter这个注解（类）本身
          {
              //这里拿的是注解的实例化对象
              Mycharacter mc= (Mycharacter) c1.getDeclaredAnnotation(Mycharacter.class);//形参是class类型，目的：他要拿到某个注解类的实例化对象，所以我要提供一个注解类（他也要求提供一个class类型的）
              System.out.println(mc.name());
              System.out.println(mc.age());
              System.out.println(mc.address());
           //   Assert.assertEquals("尝试一些", "小明",mc.name());锻炼一下这个知识点
          }

       }
       // 拿到方法注解
    @Test
    public void func2()
    {
        Class c1=demo1.class;
        try
        {
            Method m=c1.getDeclaredMethod("func1");//我这里自定义注解修饰的方法就叫func1，靠名字去定位
            if(m.isAnnotationPresent(Mycharacter.class))
            {
                Mycharacter mc= (Mycharacter) m.getDeclaredAnnotation(Mycharacter.class);
                System.out.println(mc.name());
                System.out.println(mc.age());
                System.out.println(mc.address());
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    //测试一下 getdeclaredannotations()方法
    @Test
    public void func3()
    {
        Class c1=demo1.class;
        try
        {
            Method m=c1.getDeclaredMethod("func1");//我这里自定义注解修饰的方法就叫func1，靠名字去定位
            Annotation[]mc =m.getDeclaredAnnotations();//拿到的是数组，因为一个方法可以有多个注解（）
            for(Annotation m1:mc)
//            { if (m1 instanceof Mycharacter)//他拿到的可能是各种两种甚至是三种注解类的实例化对象。所以还是需要判断一下
//               {
//                   Mycharacter m2= (Mycharacter) m1;
//                System.out.println(m2.name());
//                System.out.println(m2.age());
//                System.out.println(m2.address());
//               }

//            {
//               Class c2= m1.getClass();
//               Method[] m3 =c2.getDeclaredMethods();
//               for(Method fd:m3)
//               {
//                  fd.setAccessible(true);
//                   System.out.println(fd.getName()+":"+fd.invoke(m1));
//               }
//
//            }
            {
                if (m1 instanceof Mycharacter) {
                    Mycharacter mycharacter = (Mycharacter) m1;
                    System.out.println("name: " + mycharacter.name());
                    System.out.println("age: " + mycharacter.age());
                    System.out.println("address: " + String.join(", ", mycharacter.address()));
                } else {
                    // 处理其他类型的注解
                    Class annotationClass = m1.annotationType();
//                    Class annotationClass= m1.getClass();
                    Method[] methods = annotationClass.getDeclaredMethods();
                    for (Method method : methods) {
                        try {
                            // 调用注解的方法并获取返回值
                            Object value = method.invoke(m1); //value 有可能拿到的是数组类型，所以要判断一下
                            if (!method.getReturnType().isArray()) {
                                System.out.println(method.getName() + ": " + value);
                                continue;
                            }
                            System.out.println(method.getName() + ": " + Arrays.toString((Object[])value));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
        }




